﻿// -----------------------------------------------------------------------
// <copyright file="DContact.cs" company="">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace DC.DCAttribute.Demo
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    using System.Runtime.Serialization;

    /*
     * VS2010, 即使原来的服务端类型没有定义任何属性，在导入的定义中，仍然会以标记DataMember特性的属性来表示。
     * 即使服务端的私有字段或私有属性被标记为DataMember，在导入的定义中，原来的私有字段或者私有属性都被定义成了公有属性。
     * 当DataMember特性应用到属性上时, 不论是客户端还是服务端，该属性必须有get和set访问器。
     * 不要将DataMember特性应用到属性上，又应用到相对应的字段上，这会导致导入的成员定义重复。
     * 
     * Serializable 用在客户端与服务端之间的面向服务互交还不够理想：
     * 1. Serializable指明类型的所有成员都是可序列化的并作为组成数据类型样式的一部分，更好的方式是能够提供一种明确参与的途径，只有契约开发者明确包含的成员蔡被放到数据契约中。
     * 2. Serializable特性强制数据类型是可序列化的，从而使得类型可以用做契约操作的参数，但它无法实现将类型作为WCF操作参数(类型的"服务"特性)与序列化能力之间的职责分离。
     * 3. Serializable不支持类型名和成员名的别名，也无法将一个新类型映射为预定义的数据契约。
     * 4. Serializable使用反射，因此可以直接操作成员字段，使得封装了字段访问的属性形同虚设(通过属性操作值)破坏了属性的封装性。
     * 5. Serializable没有直接支持版本控制，因为格式化器期望获取版本控制的所有信息。因此版本控制变得困难。
     * 
     * 不论服务端的类被被记为Serializable或DataContract。我们都可以在客户端Reference.cs中看到如下两个标记。同时使用了DataContractAttribute和SerializableAttribute 这是因为：
    *       [System.Runtime.Serialization.DataContractAttribute(Name="Contact", Namespace="http://schemas.datacontract.org/2004/07/DC.Serialization.Demo")]
    *       [System.SerializableAttribute()]
    *  注意：  传统的格式化器不能序列化只标记了DataContract特性的类。要序列化该类型，必须同时使用Serializable和DataContract特性。该类型生成的数据契约，
     *              与只应用了DataContract特性相同，同时，我们仍然要为需要序列化的成员添加DataMember特性。
     *              
     */

    [DataContract]
    public class Address
    {
        [DataMember]
        public string Country { get; set; }
        [DataMember]
        public string Province { get; set; }
        [DataMember]
        public string City { get; set; }
        [DataMember]
        public string Street { get; set; }
    }

    [DataContract]
    public class Contact
    {
        [DataMember]
        public string FirstName { get; set; }
        [DataMember]
        private string LastName { get; set; }
        [DataMember]
        public string PhoneNumber { get; set; }
        [DataMember]
        public Address Address { get; set; }
    }

    [DataContract]
    public class Customer : Contact
    {
        [DataMember]
        public string Company { get; set; }
        [DataMember]
        private Contact Contact { get; set; }

        //不会成为数据契约的一部分
        public string OtherDataMember { get; set; }
    }


    /*
     *  依赖数据契约的推断是一种不好的方式：既然WCF无法从仅有的接口定义中推断出服务契约，或者默认允许事物或可靠性，它就不应该推断数据契约。
     * 
     * 1. 如果类或结构声明为public，并且没有标记DataContract，WCF会认为DataContract特性被应用到了该类型上，而且它的所有公有成员(字段或属性)都应用了DataMember特性。
     * 2. 如果类型包含DataMember但是不包含DataContract，那么DataMember将会被忽略。 如果类型被标记为DataContract特性，就不会推断数据契约。
     */

    
    public class Address1
    {
        public string Country { get; set; }
        public string Province { get; set; }
        public string City { get; set; }
        public string Street { get; set; }
    }

    public class Contact1
    {
        public string FirstName { get; set; }
        private string LastName { get; set; }
        public string PhoneNumber { get; set; }
        public Address1 Address { get; set; }
    }

    public class Customer1 : Contact1
    {
        public string Company { get; set; }
        private Contact1 Contact { get; set; }

        //不会成为数据契约的一部分
        public string OtherDataMember { get; set; }
    }
}
